#pragma once
#include "DXAMLCommon.h"
#include "xchainedmap.h"
#include "CCompositor.h"
#include "IFrameScheduler.h"



class CompositorScheduler;
class HWTextureManager;
class UIThreadScheduler;
class CCompositorDirectManipulationViewport;
class HWCompTreeNode;
class HWInstance;
class CUIElement;
class CWeakRefManager;
class HWCrossFrameResources;
class HWFrameData;
class HWFrameKeyedMutexBuffer;
class CWeakRef;
class CFrameRate;
class BrushCloneList;

class CTimeManager;


class CHardwareCompositor :
	public CCompositor,
	public IFrameScheduler
{

public: 
	static HRESULT     Create(CompositorScheduler * pCompositorScheduler, CMetaCompositor * pMetaCompositor, struct IPALPresentMethod * pIPresentMethod, CHardwareCompositor * * ppCompositor);
	virtual XUINT32    AddRef();
	virtual XUINT32    Release();
	virtual HRESULT    ExecutePresent(struct IPALPresentParameters * pIPresentParameters);
	virtual XBOOL      CanPresentImmediately();
	virtual HRESULT    GetRefreshRateInfo(struct IPALRefreshRateInfo * * ppRefreshRateInfo);
	virtual XBOOL      RequiresSynchronousPresents();
	virtual HRESULT    SubmitClear(XUINT32 uColor);
	virtual HRESULT    SubmitRetarget(XBOOL wakeUpCompositionThread, struct IPALPresentTarget * pIPresentTarget);
	virtual HRESULT    EnsurePresent(struct IPALPresentParameters * pIPresentParameters);
	HRESULT      SubmitCurrentDrawList();
	void         CleanupPreviousDrawLists();
	HRESULT      SubmitTimeManager(CTimeManager * pTimeManager);
	HRESULT      SubmitCompositionTree(const struct XRECTF_WH & backBufferSize);
	HRESULT      SubmitNewCompositorDirectManipulationViewport(CCompositorDirectManipulationViewport * pCompositorDirectManipulationViewport);
	HRESULT      SubmitOldCompositorDirectManipulationViewport(struct IObject * pCompositorViewport);
	HRESULT      SubmitDirectManipulationContentsMap(xchainedmap<void *,HWCompTreeNode *> * pDirectManipulationContentToCompositorTreeNodeMap);
	HRESULT      SubmitDrawCounters(XUINT32 uiThreadFrameRate, XFLOAT uiThreadCPUTime);
	HRESULT      SubmitMediaUpdateCommand(struct IMediaUpdateListener * pListener);
	HRESULT      SubmitTextureUpdates(HWTextureManager * pTextureManager);
	HRESULT      SubmitDCompUpdates(struct IPALDCompTreeHost * pDCompTreeHost);
	HRESULT      SubmitNotifyWindowResizeCommand(XUINT32 applicationViewState);
	HRESULT      Tick(XDOUBLE currentTickTime);
	HRESULT      Render(XBOOL * pHasDMViewport);
	HRESULT      PreRender(UIThreadScheduler * pUIThreadScheduler);
	HRESULT      PostRender();
	CFrameRate * GetFrameRateCounter();
	HRESULT      EnsureDeviceResources(struct IPALPresentTarget * pPresentTarget);
	HRESULT      EnsureDCompResources(struct IPALPresentTarget * pPresentTarget);
	HRESULT      SetDirectManipulationContentToCompositorTreeNodeMap(xchainedmap<void *,HWCompTreeNode *> * pDirectManipulationContentToCompositorTreeNodeMap);
	HRESULT      AddCompositorDirectManipulationViewport(CCompositorDirectManipulationViewport * pCompositorDirectManipulationViewport);
	HRESULT      RemoveCompositorDirectManipulationViewport(const struct IObject * pCompositorViewport);
	HRESULT      PickupDirectManipulationViewportChanges();
	HRESULT      SubmitDirectManipulationViewportChanges();
	HRESULT      ProcessDirectManipulationViewports();
	void         TickManipulations();
	HRESULT      CreateKeyedMutexBuffer(struct IPALOptimizedGraphicsDevice * pUIThreadDevice, HWFrameKeyedMutexBuffer * * ppKeyedMutexBuffer);
	XBOOL        IsFrameDirty();
	void         SetFrameDirty();
	XBOOL        HasIndependentAnimations();
	void         SetHasIndependentAnimations();
	XUINT32      GetScheduledIntervalInMilliseconds(XDOUBLE currentTickTimeInSeconds);
	virtual HRESULT RequestAdditionalFrame(XUINT32 nextTickInterval);
	HRESULT AddEvent(struct IPALWaitable * pEvent);
	void    CleanupGPUEvents();
	void    WaitForGPUWork();
	XBOOL  IsPresentMethodInitialized();
	XBOOL  HasSecondaryRoot(CUIElement * pSecondaryRoot);
	HRESULT EnsureSecondaryRoot(CWeakRefManager * pWeakRefManager, CUIElement * pSecondaryRoot);
	HWInstance * GetPersistentRenderDataSentinel();
	HWCrossFrameResources * GetCrossFrameResources();
	void SetUsedForRendering(XBOOL usedForRendering);
	XBOOL UsedForRendering();
	void SetCompositorTree(HWCompTreeNode * pRootNode, BrushCloneList * pBrushClones);
	HWFrameData * GetLastFrameData();
	HRESULT PostPresentSchedule();
	void UpdateBatchAndPrimitiveCounts(XUINT32 batchCount, XUINT32 primitiveCount);
	void OnNotifyWindowResize(XUINT32 applicationViewState);
	void SetHasRenderedContent(XBOOL hasRenderedContent);
	XBOOL HasRenderedContent();

private: 
	CHardwareCompositor(CompositorScheduler * pCompositorScheduler, CMetaCompositor * pMetaCompositor);
	virtual ~CHardwareCompositor();
	HRESULT Initialize(struct IPALPresentMethod * pIPresentMethod);
	HRESULT AddPreDrawCommand(struct IPreDrawCommand * pCommand);
	HRESULT ExecutePreDrawCommands(UIThreadScheduler * pUIThreadScheduler);
	HRESULT ProcessDirectManipulationViewportValuesChange(CCompositorDirectManipulationViewport * pCompositorDirectManipulationViewport);
	void ReleaseList(xvector<CCompositorDirectManipulationViewport *> * pList);
	HRESULT PropagateViewportListWhenNotEmpty(xvector<CCompositorDirectManipulationViewport *> * pSourceList, xvector<CCompositorDirectManipulationViewport *> * * ppDestList, XBOOL clearSourceList);


private: 
	HWCompTreeNode * m_pCurrentRootCompNode;
	BrushCloneList * m_pCurrentBrushCloneList;
	HWInstance * m_pRenderDataSentinel;
	CWeakRef * m_pSecondaryRoot;
	xvector<CCompositorDirectManipulationViewport *> * m_pCompositorDirectManipulationViewportsUIThread;
	xvector<CCompositorDirectManipulationViewport *> * m_pCompositorDirectManipulationViewportsRenderThreadWaiting;
	xvector<CCompositorDirectManipulationViewport *> * m_pCompositorDirectManipulationViewportsRenderThread;
	xchainedmap<void *,HWCompTreeNode *> * m_pDirectManipulationContentToCompositorTreeNodeMap;
	CompositorScheduler * m_pCompositorScheduler;
	HWCrossFrameResources * m_pCrossFrameResources;
	struct IPALCriticalSection * m_pPreDrawCommandLock;
	xvector<IPreDrawCommand *> m_PreDrawCommands; 


private: 
	CFrameRate * m_pFrameRate;
	XDOUBLE m_lastTickTimeInSeconds;
	XUINT32 m_nextTickIntervalInMilliseconds;
	struct
	{
		XBOOL m_isFrameDirty:1;
		XBOOL m_hasIndependentAnimations:1;
	};

	xvector<IPALWaitable *> m_gpuEvents; 

	struct  
	{
		XBOOL m_usedForRendering:1;
		XBOOL m_hasRenderedContent:1;
	};



};